/*
引用型是按引用地址来操作

因为对象类型不再是一个简单的值，而会是很多值的集合，so需要开辟一个空间(16进制的)（相当于一个箱子）用来存放它。


操作步骤：

1. 遇到对象类型的数据，会先开辟一个新的内存空间，浏览器会分配给它一个16进制的地址（方便别人找到它）。

2. 按照一定的顺序，分别的把对象键值对存储到新开辟的内存空间当中。

3. 把开辟内存的地址赋值给变量（或则其它的东西，比如说当前元素的某个事件(oDiv.onclick = fn)），以后变量就可以通过地址找到内存空间，然后进行一些操作。

*/

var o = {name:'ahhh'}; //o = aaafff111
var p = o; //p = aaafff111
p.name = 'ahhh2'; //p通过地址找到对应的内存空间，再把里面的name改成ahhh2
console.log(o.name);  //ahhh2


var m = {name: 'ahhh'};
var n = m;
n = {name: 'ahhh2'};
console.log(m.name); //ahhh


/*
下面栗子，在堆内存中存obj的时候，遇到fn，发现是一个函数自执行，于是开始函数自执行，开辟一个栈内存，形参赋值，变量提升，逐行执行，然后return function，因为是function，此时会另外再开辟一个堆内存，返回堆内存的地址，作为return 返回的值。
*/
/*var n = 10;
var obj = {
    n:20
    ,fn:
    //赋值 赋值 必须先有一个值
    //堆内存保存的是 键 值 对
        (function(){
            //->上级作用域:全局作用域
            var n = 30;
            //↓不会提升 因为只会对等号左边进行提升 况且这个还没有名字
            return function(){
                //->上级作用域：自执行函数
                console.log(n);
            }
        })()
};

obj.fn();*/

var n = 10;
var obj = {
    n:20
    ,fn:
    //赋值 赋值 必须是一个值被复
    //堆内存保存的是 键 值 对
        (function(n){
            //->上级作用域:全局作用域
            var n = 30;
            //↓不会提升 因为只会对等号左边进行提升 况且这个还没有名字
            return function(){
                //->上级作用域：自执行函数
                console.log(n);
            }
        })(obj.n) //报错 TypeError: Cannot read property 'n' of undefined //此时该堆内存还没有保存完键值对，地址还没有赋给obj，我们是无法通过obj.n访问到的 obj此时的值是undefined
};

obj.fn();

/*
关于常量：
const常量之所以无法改变，就是因为定死了地址（地址对应的空间内的内容不是定死的），故它叫“常”而不叫“变”，这个“量”你可以认为它就是地址，不变的地址，可变的地址。
*/

const a = {name: 'ahhh', age: 20};
// a = {};//报错 TypeError: Assignment to constant variable.
a.age = 31;
console.log(a); //{ name: 'ahhh', age: 31 }